#include "GameState.h"
#include "Base/BPL.h"
#include "SFMLContext.h"
#include "GraphicComponents.h"
#include "PhysicComponents.h"
#include "PositionComponent.h"
#include "CharacterComponent.h"
#include "LifeComponent.h"
#include "ScriptComponent.h"
#include "MapLoader.h"

GameState::GameState() : State()
{

}

GameState::~GameState()
{
    BPL::Logger::log("delete gameState");
}

void GameState::enter()
{
    mpt_entityManager = new BPL::EntityManager;
    mpt_renderSystem = new RenderSystem;
    mpt_physicSystem = new PhysicSystem;
    mpt_playerSystem = new PlayerSystem;
    mpt_cameraSystem = new CameraSystem;
	mpt_bulletSystem = new BulletSystem;
	mpt_damageSystem = new DamageSystem;
	mpt_scriptSystem = new ScriptSystem;
	mpt_particuleSystem = new ParticuleSystem;

    BPL::Context* context = getParent()->getParent();
    context->getInput()->addObs(mpt_cameraSystem);
	context->getInput()->addObs(mpt_playerSystem);

	sf::RenderWindow* app = ((SFMLContext*)context)->getApp();
    mpt_renderSystem->attachApp(app);
    mpt_cameraSystem->attachApp(app);
	mpt_physicSystem->attachApp(app);
	mpt_bulletSystem->attachApp(app);
	mpt_damageSystem->attachApp(app);
	mpt_scriptSystem->attachApp(app);
	mpt_particuleSystem->attachApp(app);
	mpt_playerSystem->attachApp(app);

	mpt_renderSystem->setParent(this);
    mpt_cameraSystem->setParent(this);
	mpt_physicSystem->setParent(this);
	mpt_bulletSystem->setParent(this);
	mpt_damageSystem->setParent(this);
	mpt_scriptSystem->setParent(this);
	mpt_particuleSystem->setParent(this);
	
	sf::Vector2i playerPos(2,2);
	mpt_playerSystem->setParent(this);

	MapLoader loader;
	loader.load("Data/map1.tmx", mpt_entityManager, this);
	//_addPlayerIn(playerPos);

	/*_addBlockIn(sf::Vector2i(1,10));
	_addBlockIn(sf::Vector2i(2,10));
	_addBlockIn(sf::Vector2i(3,10));
	_addBlockIn(sf::Vector2i(4,10));
	_addBlockIn(sf::Vector2i(5,10));
	_addBlockIn(sf::Vector2i(6,10));
	_addBlockIn(sf::Vector2i(7,10));

	_addBlockIn(sf::Vector2i(3,9));
	_addBlockIn(sf::Vector2i(4,9));
	_addBlockIn(sf::Vector2i(5,9));
	_addSlopeBlockIn(sf::Vector2i(6,9),false);
	_addSlopeBlockIn(sf::Vector2i(5,8),false);
	_addBlockIn(sf::Vector2i(4,8));
	
	_addSlopeBlockIn(sf::Vector2i(3,8),true);
	_addSlopeBlockIn(sf::Vector2i(2,9),true);

	_addBlockIn(sf::Vector2i(2,6));
	_addEnemyIn(sf::Vector2i(1,9));

	for(int i = 0; i < 20; i++)
    {
        _addBlockIn(sf::Vector2i(0,i));
		_addBlockIn(sf::Vector2i(i,0));
		_addBlockIn(sf::Vector2i(20,i));
		_addBlockIn(sf::Vector2i(i,20));
    }*/

	
}

void GameState::exit()
{
	delete mpt_entityManager;
    delete mpt_renderSystem;
    delete mpt_physicSystem;
    delete mpt_playerSystem;
    delete mpt_cameraSystem;
	delete mpt_bulletSystem;
	delete mpt_damageSystem;
	delete mpt_scriptSystem;
	delete mpt_particuleSystem;
}

bool GameState::pause()
{
    return true;
}

void GameState::resume()
{

}

void GameState::update(double time)
{
    mpt_playerSystem->update(time);
	mpt_bulletSystem->update(time);
	mpt_damageSystem->update(time);
	mpt_particuleSystem->update(time);
	mpt_scriptSystem->update(time);
    mpt_physicSystem->update(time);
	mpt_cameraSystem->update(time);
	mpt_renderSystem->update(time);
}

void GameState::_addBlockIn(const sf::Vector2i& position)
{
	BPL::EntityPtr e(new BPL::Entity(mpt_entityManager->getNextAvailableID()));
    mpt_entityManager->registerStaticEntity(e, position);
	
	//GraphicComponentPtr graph (new GraphicComponent);
	ModelGraphicComponentPtr graph (new ModelGraphicComponent);
    StaticComponentPtr phys (new StaticComponent);
	PositionComponentPtr pos (new PositionComponent);
	LifeComponentPtr lifeC (new LifeComponent);

	int sizeTile = mpt_entityManager->sizeTile;
	
	pos->m_position=sf::Vector2f(position.x*sizeTile,position.y*sizeTile);
	graph->model.loadModel("Data/tileGrass.mdl");
	phys->typeStatic = StaticComponent::FULL;
	lifeC->life = 200;

    mpt_entityManager->addComponent<GraphicComponent>((BPL::EntityId)e->getID(), graph);
    mpt_entityManager->addComponent<PhysicComponent>((BPL::EntityId)e->getID(), phys);
	mpt_entityManager->addComponent<PositionComponent>((BPL::EntityId)e->getID(), pos);
	//mpt_entityManager->addComponent<LifeComponent>((BPL::EntityId)e->getID(), lifeC);

    mpt_renderSystem->addEntity(e->getID());
    mpt_physicSystem->addEntity(e->getID());
	//mpt_damageSystem->addEntity(e->getID());
}

void GameState::_addPlayerIn(const sf::Vector2i& position)
{
	int sizeTile = mpt_entityManager->sizeTile;
	BPL::EntityPtr e(new BPL::Entity(mpt_entityManager->getNextAvailableID()));
	mpt_entityManager->registerDynamicEntity(e, sf::Vector2f(position.x * sizeTile, position.y * sizeTile),0);
	
	GraphicComponentPtr graph (new GraphicComponent);
    JumpingComponentPtr phys (new JumpingComponent);
	PositionComponentPtr pos (new PositionComponent);
	CharacterComponentPtr charac (new CharacterComponent);
	
	pos->m_position=sf::Vector2f(position.x*sizeTile,position.y*sizeTile);
	phys->sizeBox = sf::Vector2f(20,30);
	phys->jumpSpeed = 600.0f;
    phys->speed = 120;
	phys->jumpLength = 3;

	sf::RectangleShape* rect = new sf::RectangleShape(sf::Vector2f(20, 30));
	rect->setFillColor(sf::Color(20,200,40));
		
	graph->m_sprite = rect;
    graph->m_transform.setPosition(pos->m_position);
	
    mpt_entityManager->addComponent<GraphicComponent>((BPL::EntityId)e->getID(), graph);
	mpt_entityManager->addComponent<CharacterComponent>((BPL::EntityId)e->getID(), charac);
    mpt_entityManager->addComponent<PhysicComponent>((BPL::EntityId)e->getID(), phys);
	mpt_entityManager->addComponent<PositionComponent>((BPL::EntityId)e->getID(), pos);

    mpt_renderSystem->addEntity(e->getID());
    mpt_physicSystem->addEntity(e->getID());
	mpt_playerSystem->addEntity(e->getID());
	mpt_cameraSystem->addEntity(e->getID());
}

void GameState::_addEnemyIn(const sf::Vector2i& position)
{
	int sizeTile = mpt_entityManager->sizeTile;
	BPL::EntityPtr e(new BPL::Entity(mpt_entityManager->getNextAvailableID()));
	mpt_entityManager->registerDynamicEntity(e, sf::Vector2f(position.x * sizeTile, position.y * sizeTile),0);
	
	GraphicComponentPtr graph (new GraphicComponent);
    JumpingComponentPtr phys (new JumpingComponent);
	PositionComponentPtr pos (new PositionComponent);
	LifeComponentPtr life (new LifeComponent);
	ScriptComponentPtr script (new ScriptComponent);

	script->file = "Data/test.lua";
	script->fromFile = true;
	
	pos->m_position=sf::Vector2f(position.x*sizeTile,position.y*sizeTile);
	phys->sizeBox = sf::Vector2f(20,30);
	phys->jumpSpeed = 600.0f;
    phys->speed = 120;
	phys->jumpLength = 3;

	life->life=200;

	sf::RectangleShape* rect = new sf::RectangleShape(sf::Vector2f(20, 30));
	rect->setFillColor(sf::Color(60,20,140));
		
	graph->m_sprite = rect;
    graph->m_transform.setPosition(pos->m_position);
	
    mpt_entityManager->addComponent<GraphicComponent>((BPL::EntityId)e->getID(), graph);
	mpt_entityManager->addComponent<LifeComponent>((BPL::EntityId)e->getID(), life);
    mpt_entityManager->addComponent<PhysicComponent>((BPL::EntityId)e->getID(), phys);
	mpt_entityManager->addComponent<PositionComponent>((BPL::EntityId)e->getID(), pos);
	mpt_entityManager->addComponent<ScriptComponent>((BPL::EntityId)e->getID(), script);

    mpt_renderSystem->addEntity(e->getID());
    mpt_physicSystem->addEntity(e->getID());
	mpt_damageSystem->addEntity(e->getID());
	mpt_scriptSystem->addEntity(e->getID());
}

void GameState::_addSlopeBlockIn(const sf::Vector2i& position, bool left)
{
	BPL::EntityPtr e(new BPL::Entity(mpt_entityManager->getNextAvailableID()));
    mpt_entityManager->registerStaticEntity(e, position);
	
	ModelGraphicComponentPtr graph (new ModelGraphicComponent);
    StaticComponentPtr phys (new StaticComponent);
	PositionComponentPtr pos (new PositionComponent);

	int sizeTile = mpt_entityManager->sizeTile;
	
	if(left)
	{
		graph->model.loadModel("Data/tileGrassSL.mdl");
		phys->typeStatic = StaticComponent::SLOPELEFT;
	}
	else
	{
		graph->model.loadModel("Data/tileGrassSR.mdl");
		phys->typeStatic = StaticComponent::SLOPERIGHT;
	}
	pos->m_position=sf::Vector2f(position.x*sizeTile,position.y*sizeTile);
	
    mpt_entityManager->addComponent<GraphicComponent>((BPL::EntityId)e->getID(), graph);
    mpt_entityManager->addComponent<PhysicComponent>((BPL::EntityId)e->getID(), phys);
	mpt_entityManager->addComponent<PositionComponent>((BPL::EntityId)e->getID(), pos);

    mpt_renderSystem->addEntity(e->getID());
    mpt_physicSystem->addEntity(e->getID());
}